package whf.framework.util;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;

import whf.framework.entity.Entity;
import whf.framework.exception.NotFoundException;
import whf.framework.log.Log;
import whf.framework.log.LogFactory;
import whf.framework.service.Service;
import whf.framework.tools.generator.GeneratorException;

/**
 * @author wanghaifeng
 *
 */
public class Utils {
	private static Log log = LogFactory.getLog(Utils.class);

	/**
	 * @modify wanghaifeng Sep 12, 2006 11:39:48 PM
	 * @param cls
	 * @param property
	 * @return
	 */
	public static Field getDeclaredField(Class cls, String property){
		try{
			return cls.getDeclaredField(property);
		}catch(Exception e){
			log.debug(e);
			return null;
		}
	}
	/**
	 * 获取一个类的一个属性的对象类型，如int 1则输出new Integer(1);
	 * @param cls
	 * @param property
	 * @param value
	 * @return
	 */
	public static Object getPropertyObject(Class cls, String property, Object value){
		Field field = getDeclaredField(cls, property);
		if(field != null){
			if(field.getType().isPrimitive()){
				return new Double(Double.parseDouble(value.toString()));
			}else{
				if(TypeUtils.isExtendsFrom(field.getType(),Date.class)){
					if(StringUtils.isNumeric(value.toString())){
						return new Date(Long.parseLong(value.toString()));
					}else{
						SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
						try{
							return sdf.parse(value.toString());
						}catch(Exception e){
							return value;
						}
					}
				}else{
					return value;
				}
			}
		}
		return value;
	}

	/**
	 * @modify wanghaifeng Sep 12, 2006 11:39:41 PM
	 * @param tableName
	 * @param tablePre
	 * @return
	 */
	public static String getBoClassName(String tableName, String tablePre){
		String boClassName = tableName;
		if(tablePre!= null && tableName.startsWith(tablePre)){
			boClassName = boClassName.substring(tablePre.length());
		}
		boClassName = StringUtils.capitalize(getPropertyName(boClassName));
		return boClassName;
	}
	
	/**
	 * @modify wanghaifeng Sep 12, 2006 11:39:44 PM
	 * @param field
	 * @return
	 */
	public static String getPropertyName(String field) {
		String[] ss = StringUtils.split(field, "_");
		String res = ss[0].toLowerCase();
		for (int i = 1; i < ss.length; i++) {
			res += StringUtils.capitalize(ss[i].toLowerCase());
		}
		return res;
	}

	/**
	 * @modify wanghaifeng Sep 12, 2006 11:39:38 PM
	 * @param type
	 * @param colTypei
	 * @return
	 */
	public static String getMapType(String type, int colTypei) {
		if(Long.class.getName().equals(type)){
			return "long";
		}else if(StringUtils.equalsIgnoreCase("bigint",type)){
			return "long";
		}else if(Integer.class.getName().equals(type)){
			return "int";
		}else if(type.toLowerCase().indexOf("int") != -1){
			return "int";
		}else if(String.class.getName().equals(type)){
			return "String";
		}else if(type.toLowerCase().indexOf("char") != -1){
			return "String";
		}else if(type.toLowerCase().indexOf("text") != -1){
			return "String";
		}else if(type.toLowerCase().indexOf("datetime")!=-1 || type.toLowerCase().indexOf("timestamp") != -1){
			return Timestamp.class.getName();
		}else if(type.toLowerCase().indexOf("date") != -1){
			return Date.class.getName();
		}else if(type.toLowerCase().indexOf("time") != -1){
			return Time.class.getName();
		}else if(Math.abs(colTypei) == Types.BLOB){
			return Blob.class.getName();
		}else if(type.toLowerCase().indexOf("blob") != -1){
			return Blob.class.getName();
		}else if(Math.abs(colTypei) == Types.CLOB){
			return Clob.class.getName();
		}else if(type.toLowerCase().indexOf("clob") != -1){
			return Clob.class.getName();
		}else if(StringUtils.equalsIgnoreCase("bit", type)){
			return "boolean";
		}
		
		return type;
	}
	
	private static Map<String, Class> classCache = Utils.newHashMap();
	/**
	 * @modify wanghaifeng Sep 12, 2006 11:39:35 PM
	 * @param className
	 * @return
	 */
	public static Class getClassByClassName(String className){
		if(className == null) return null;
		try{
			Class result = classCache.get(className);
			if(result == null) {
				result = Class.forName(className);
				classCache.put(className, result);
			}
			return result;
		}catch(ClassNotFoundException e){
			return null;
		}
	}

    /**
     * @modify wanghaifeng Sep 12, 2006 11:39:32 PM
     * @param x
     * @return
     */
    public static int hash(Object x) {
        int h = x.hashCode();

        h += ~(h << 9);
        h ^=  (h >>> 14);
        h +=  (h << 4);
        h ^=  (h >>> 10);
        return h;
    }
    
    /**
     * @modify wanghaifeng Sep 12, 2006 11:39:29 PM
     * @param <K>
     * @param <V>
     * @return
     */
    public static <K,V> Map<K,V> newHashMap() { 
        return new HashMap<K,V>();  
    }
    
    /**
     * @modify wanghaifeng Sep 12, 2006 11:39:26 PM
     * @param <T>
     * @return
     */
    public static <T> java.util.List<T> newArrayList(){
    	return new ArrayList<T>(10);
    }
    
    /**
     * @modify wanghaifeng Sep 12, 2006 11:39:24 PM
     * @param <T>
     * @return
     */
    public static<T> java.util.Set<T> newHashSet(){
    	return new HashSet<T>();
    }
    
    /**
     * 将数组对象转变为Map
     * @param <K>
     * @param <V>
     * @param keys
     * @param values
     * @return
     */
    public static <K, V> Map<K, V> toMap(K[] keys, V[] values){
    	if(keys == null) throw new IllegalArgumentException("Keys can't be empty!");
    	Map<K, V> result = newHashMap();
    	for(int i=0; i< keys.length; i++){
    		V v = null;
    		if(values.length >= i) 
    			v = values[i];
    		result.put(keys[i], v);
    	}
    	return result;
    }

	/**
	 * 创建目录
	 * @modify wanghaifeng Sep 12, 2006 11:39:18 PM
	 * @param path
	 * @throws GeneratorException
	 */
	public static void mkdir(String path) {
		File pdir = new File(path);
		if (pdir.exists())
			return;
		String[] paths = StringUtils.split(path, File.separator);
		String p = "";
		for (int i = 0; i < paths.length; i++) {
			p += paths[i];
			p += File.separator;
			File dir = new File(p);
			if (!dir.exists()) {
				boolean b = dir.mkdir();
				if (!b) {
					throw new IllegalArgumentException("Create dir failure:" + p);
				}
			}
		}
	}
	
	/**
	 * 如果是文件，直接删除该文件，如果是目录，这首先删除目录中所有内容，然后删除该目录
	 * @modify wanghaifeng Jan 17, 2007 11:41:05 AM
	 * @param file
	 */
	public static void del(File file){
		if(file == null || !file.exists()) return;
		if(file.isFile()){
			file.delete();
		} else if(file.isDirectory()){
			File[] files = file.listFiles();
			for(File f: files){
				del(f);
			}
			file.delete();
		}
	}
	
	/**
	 * 同步集合和主键列表中的值
	 * @modify wanghaifeng Sep 12, 2006 11:48:49 PM
	 * @param set  原对象集合
	 * @param ids  对象的主键列表
	 * @param service  能够找到对象的服务对象
	 * @return true:发生改变， false:未发生改变
	 * @throws NotFoundException
	 */
	public static boolean syncCollection(Collection set, long[] ids, Service service) throws NotFoundException{
		if(set == null || set.size() == 0 || ids == null || ids.length == 0 || service  == null) return false;
		boolean changed = false;
		for(Iterator it = set.iterator(); it.hasNext(); ){
			Entity bo = (Entity)it.next();
			boolean found = false;
			for(long id: ids){
				if(id == bo.getId()){
					found = true;
					break;
				}
			}
			if(!found){
				it.remove();
				changed = true;
			}
		}
		for(long id: ids){
			if(id == 0) continue;
			boolean found = false;
			for(Iterator it = set.iterator(); it.hasNext(); ){
				Entity bo = (Entity)it.next();
				if(bo.getId() == id){
					found = true;
					break;
				}
			}
			if(!found){
				set.add(service.findByPrimaryKey(new Long(id)));
				changed = true;
			}
		}
		return changed;
	}
	
	/**
	 * 使用参数最小的构造函数构造类实例
	 * @modify wanghaifeng Dec 26, 2006 3:53:04 PM
	 * @param cls
	 * @return
	 */
	public static Object constructBean(Class cls){
		if(cls == null) throw new IllegalArgumentException("Class is empty!");
		Constructor[] constructors = cls.getConstructors();
		int paramCount = 0;
		while(paramCount < 10){
			for(Constructor c: constructors){
				Class[] parameterTypes = c.getParameterTypes();
				if(parameterTypes.length == paramCount){
					Object[] params = new Object[paramCount];
					for(int i=0; i< paramCount; i++){
						params[i] = null;
					}
					try{
						return c.newInstance(params);
					}catch(Exception e){
						//ignore
					}
				}
			}
			paramCount ++;
		}
		return null;
	}
	
	public static Object constructBean(Class cls, Object[] params){
		if(cls == null) throw new IllegalArgumentException("Class is empty!");
		try{
			Class paramTypes[] = new Class[params.length];
			for(int i=0; i< params.length; i++){
				paramTypes[i] = params[i].getClass();
			}
			Constructor c = cls.getConstructor(paramTypes);
			return c.newInstance(params);
		}catch(Exception e){
			return null;
		}
	}
	
	/**
	 * 判断一个对象是否存在数组中
	 * @param obj 对象
	 * @param arr 对象数组
	 * @return
	 */
	public static boolean in(Object obj, Object[] arr){
		if(obj == null || arr == null) return false;
		for(Object ele: arr){
			if(obj.equals(ele)) return true;
		}
		return false;
	}
	
	public static void main(String[] args) throws Exception {
		Map<String, Map<String, Object>> map = newHashMap();
		System.out.println(map);
	}
}
